package com.bestcem.xm.survey.export.type;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.survey.export.BaseTypeHandler;
import com.bestcem.xm.survey.grpc.client.dto.QstructsDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

import static com.bestcem.xm.survey.enums.QuestionTypeEnum.QUESTION_TYPE_MULTIPLE;
import static com.bestcem.xm.survey.util.SurveyConstant.SCORE_RULE_ALL_RIGHT;

@Slf4j
@Component
public class MultipleHandler implements BaseTypeHandler {

    @Override
    public Map<String, String> getSelectColumnChangeDictV2(JSONObject data, String dtype) {
        Map<String, String> column_change_dict = new HashMap();
        //选项选项
        List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> column_change_dict.put(getSelectRealcolV2(data, v), getSelectReadablecolV2(data, v)));
        return column_change_dict;
    }

    private String getSelectRealcolV2(JSONObject data, JSONObject item) {
        //cid:题目可见编号
        return String.format("%s__%s", data.getString("cid"), item.get("oid"));
    }

    private String getSelectReadablecolV2(JSONObject data, JSONObject item) {
        //cid:题目可见编号
        return String.format("%s__%s", BaseTypeHandler.clearHtml(data.getString("title")), BaseTypeHandler.clearHtml(item.getString("title")));
    }

    @Override
    public Map<String, String> getOpenColumnChangeDictV2(JSONObject data) {
        Map<String, String> res = new HashMap();
        List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> {
            if (isOpenRow(v)) {
                res.put(getOpenRealcolV2(data, v), getOpenReadablecolV2(data, v));
            }
        });
        return res;
    }

    private String getOpenRealcolV2(JSONObject data, JSONObject item) {
        return String.format("%s__%s__open", data.getString("cid"), item.getString("oid"));
    }

    private String getOpenReadablecolV2(JSONObject data, JSONObject item) {
        return String.format("%s__%s__开放", BaseTypeHandler.clearHtml(data.getString("title")), BaseTypeHandler.clearHtml(item.getString("title")));
    }

    @Override
    public Map<String, String> getScoreColumnChangeDictV2(JSONObject data, QstructsDto qStruct) {
        Map<String, String> res = new HashMap();
        JSONObject scores = JSONObject.parseObject(qStruct.getScores());
        if (!scores.isEmpty() && scores.containsKey(data.getString("gid"))) {
            res.put(getScoreRealcolV2(data), getScoreReadablecolV2(data));
        }
        return res;
    }

    private String getScoreRealcolV2(JSONObject data) {
        return String.format("%s__score", data.getString("cid"));
    }

    private String getScoreReadablecolV2(JSONObject data) {
        return String.format("%s__评分", BaseTypeHandler.clearHtml(data.getString("title")));
    }

    @Override
    public List<String> getSelectColumnListV2(JSONObject data, String dtype) {
        List<String> column_list = new ArrayList();
        List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> column_list.add(getSelectRealcolV2(data, v)));
        return column_list;
    }

    @Override
    public List<String> getOpenColumnListV2(JSONObject data) {
        List<String> res = new ArrayList();
        List<JSONObject> items = (List<JSONObject>) data.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> {
            if (isOpenOption(v)) {
                res.add(getOpenRealcolV2(data, v));
            }
        });
        return res;
    }

    @Override
    public List<String> getScoreColumnListV2(JSONObject data, QstructsDto qStruct) {
        List<String> res = new ArrayList();
        JSONObject scores = JSONObject.parseObject(qStruct.getScores());
        if (!scores.isEmpty() && scores.containsKey(data.getString("gid"))) {
            res.add(getScoreRealcolV2(data));
        }
        return res;
    }

    @Override
    public Map<String, Map<Object, Object>> getConvertTableV2(JSONObject q) {
        Map<String, Map<Object, Object>> convert_table = new HashMap();
        List<JSONObject> items = (List<JSONObject>) q.getOrDefault("items", Collections.emptyList());
        items.forEach(v -> {
            Map<Object, Object> res = new HashMap<>(4);
            //Base.UNSELECT_OPTION_NAN 可以理解为null
            res.put(0, null);
            res.put(1, "选择");
            convert_table.put(getSelectRealcolV2(q, v), res);
        });
        return convert_table;
    }

    @Override
    public Map<Object, Object> getSelectAnswerDictV2(JSONObject dataValue, Object answers, String dtype, Boolean score_apply_type) {
        Map<Object, Object> data = new HashMap<>();
        List<JSONObject> items = (List<JSONObject>) dataValue.getOrDefault("items", Collections.emptyList());
        if (Objects.isNull(answers)) {
            //np.nan 可以理解为null
            items.forEach(v -> data.put(getSelectRealcolV2(dataValue, v), null));
        } else {
            List<List> answerData = (List<List>) answers;
            items.forEach(item -> {
                if (CollUtil.isNotEmpty(answerData)) {
                    for (List answer : answerData) {
                        if (item.getInteger("gid").equals(answer.get(0))) {
                            if ("readable".equals(dtype)) {
                                data.put(getSelectRealcolV2(dataValue, item), BaseTypeHandler.clearHtml((String) item.getOrDefault("title", "")));
                            } else if ("not01".equals(dtype) || "anothernot01".equals(dtype)) {
                                //np.nan 可以理解为null
                                data.put(getSelectRealcolV2(dataValue, item), item.getOrDefault("oid", null));
                            } else {
                                data.put(getSelectRealcolV2(dataValue, item), 1.0);
                            }
                            break;
                        }
                    }
                } else {
                    if ("readable".equals(dtype)) {
                        //np.nan 可以理解为null
                        data.put(getSelectRealcolV2(dataValue, item), null);
                    } else if ("not01".equals(dtype) || "anothernot01".equals(dtype)) {
                        data.put(getSelectRealcolV2(dataValue, item), null);
                    } else {
                        data.put(getSelectRealcolV2(dataValue, item), 0.0);
                    }
                }
            });
        }
        return data;
    }


    @Override
    public Map<Object, Object> getOpenAnswerDictV2(JSONObject dataValue, Object answers) {
        Map<Object, Object> data = new HashMap<>();
        List<JSONObject> items = (List<JSONObject>) dataValue.getOrDefault("items", Collections.emptyList());
        if (Objects.isNull(answers)) {
            items.forEach(item -> {
                if (isOpenOption(item)) {
                    data.put(getOpenRealcolV2(dataValue, item), null);
                }
            });
        } else {
            items.forEach(item -> {
                if (isOpenOption(item)) {
                    for (Object answer : ((List<Object>) answers)) {
                        if (answers instanceof List && (item.getInteger("gid").equals(((List) answer).get(0)) && ((List) answer).size() > 1)) {
                            data.put(getOpenRealcolV2(dataValue, item), BaseTypeHandler.clearHtml((String) ((List) answer).get(1)));
                            break;
                        }
                    }
                    data.putIfAbsent(getOpenRealcolV2(dataValue, item), null);
                }
            });
        }
        return data;
    }

    @Override
    public Map<Object, Object> getScoreAnswerDictV2(JSONObject dataValue, Object answer, QstructsDto qstructsDto, JSONObject score_dict, String dtype) {
        Map<Object, Object> data = new HashMap<>();
        if (Objects.nonNull(qstructsDto) && StrUtil.isNotEmpty(qstructsDto.getScores())
                && JSONObject.parseObject(qstructsDto.getScores()).containsKey(dataValue.getString("gid"))) {
            //np.nan 可以理解为null
            data.put(getScoreRealcolV2(dataValue), null);
        }
        List<List> answers = ((List<List>) answer);
        if (CollUtil.isNotEmpty(answers)) {
            Float score = 0f;
            JSONObject score_config = JSONObject.parseObject(qstructsDto.getScoreConfig());
            try {
                String gid = dataValue.getString("gid");
                if ("image_select".equals(dataValue.getString("custom_qtype"))
                        || !SCORE_RULE_ALL_RIGHT.equals(score_config.getInteger(gid))
                        || !BaseTypeHandler.checkAnswerAllRight(gid, score_dict, answers, dtype)) {
                    for (List list : answers) {
                        String key = String.format("%s_%s", dataValue.getString("gid"), list.get(0));
                        if (CollUtil.isNotEmpty(score_dict) && score_dict.containsKey(key)) {
                            Float tmp_score = score_dict.getFloat(key);
                            if (Objects.nonNull(tmp_score)) {
                                score += tmp_score;
                            }
                        }
                    }
                    score = Float.parseFloat(String.format("%.2f", score));
                }
            } catch (Exception e) {
                log.error("分数转换异常：[}", e);
                //np.nan 可以理解为null
                score = null;
            }
            data.put(getScoreRealcolV2(dataValue), score);
        }
        return data;
    }

    @Override
    public List<List<String>> getVarLabelsV2(JSONObject dataValue, boolean not01, boolean need_title) {
        List<List<String>> data = new ArrayList<>();
        boolean not_need_title = !need_title;
        List var_list = new ArrayList(), val_list = new ArrayList(), head_list = new ArrayList();
        String custom_qtype = dataValue.getString("custom_qtype");
        List<JSONObject> items = (List<JSONObject>) dataValue.getOrDefault("items", Collections.emptyList());
        if ("multiple".equals(custom_qtype)) {
            items.forEach(item -> {
                var_list.add(String.format("VARIABLE LABELS %s '%s'.", getSelectColV2(dataValue, item), getTitles(dataValue, null, item, not_need_title)));
                var_list.add(String.format("%s_%s", dataValue.getString("cid"), item.getString("oid")));
            });
        } else {
            items.forEach(item -> {
                var_list.add(String.format("VARIABLE LABELS %s '%s'.", getSelectColV2(dataValue, item), getTitles(dataValue, null, item, true)));
                var_list.add(String.format("%s_%s", dataValue.getString("cid"), item.getString("oid")));
            });
        }
        getValItemsV2(dataValue, head_list, val_list, not01, true);
        data.add(var_list);
        data.add(val_list);
        return data;
    }

    private String getSelectColV2(JSONObject dataValue, JSONObject item) {
        return String.format("%s_%s", dataValue.getString("cid"), item.getString("oid"));
    }

    @Override
    public List<String> getSpssCodeV2(JSONObject param, QstructsDto qstruct) {
        List<String> head_list = new ArrayList<>();
        head_list.add(param.getString("cid"));
        List<JSONObject> items = (List<JSONObject>) param.getOrDefault("items", Collections.emptyList());
        head_list.addAll(items.stream().filter(item -> Objects.nonNull(item.getBoolean("is_open")) && item.getBoolean("is_open"))
                .map(item -> String.format("%s__%s__open", param.get("cid"), item.get("oid"))).collect(Collectors.toList()));
        if (ObjectUtil.isNotEmpty(qstruct.getScores()) && JSONObject.parseObject(qstruct.getScores()).containsKey(param.getString("gid"))) {
            head_list.add(getScoreRealcolV2(param));
        }
        return head_list;
    }

    @Override
    public String getQuestionTypeValue() {
        return QUESTION_TYPE_MULTIPLE.getValue();
    }
}
